package orm

import (
	"encoding/json"
	"fmt"
	"playbook/ginsvr/src/global"
	"playbook/ginsvr/src/utils/stringutil"
	"playbook/ginsvr/src/utils/uuidutil"

	"os"

	"strings"

	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

type FullProcess struct {
	Process Process `json:"process"`
}

type Process struct {
	Name            string                   `json:"name"`
	Overtime        string                   `json:"overtime"`
	Version         string                   `json:"version"`
	Inputparamid    string                   `json:"-"`
	Inputparameter  map[string]interface{}   `gorm:"-" json:"input-parameter"`
	Outputcontextid string                   `json:"output-context"`
	Outputparameter map[string]interface{}   `gorm:"-" json:"output-parameter"`
	Activitiesid    string                   `json:"-"`
	Activities      map[string][]interface{} `gorm:"-" json:"activities"`
	Processid       string                   `gorm:"primaryKey" json:"id"`
	Outputparamid   string                   `json:"-"`
	Transion        []Transion               `gorm:"-" json:"first-transition"`
	Catagoryid      string                   `json:"catagoryid"`
	Desc            string                   `json:"desc"`
	Projectid       string                   `json:"projectid"`
	Issubprocesss   bool                     `json:"-"`
}

type Parameter struct {
	Parameterid string `json:"-"`
	Name        string `json:"name"`
	Type        string `json:"type"`
	Optional    string `json:"optional"`
	Classpath   string `json:"classPath"`
}

type Paramrelation struct {
	Parentparamid string
	Subparamid    string
	//sub-子成员 lst-数组元素类型 mapkey-图键类型 mapval-图值类型 lstmapkey-数组图键类型 lstmapval-数组图值类型
	Reltype string
	//是否基础类型 0-是 1-否（默认值）
	Isbasetype string
	Relname    string
}

type Activity struct {
	Activityid           string                 `json:"id"`
	Name                 string                 `json:"name"`
	Inputparammappingid  string                 `json:"-"`
	Inputparammapping    map[string]interface{} `gorm:"-" json:"input-parameter-mapping"`
	Outputparammappingid string                 `json:"-"`
	Outputparammapping   map[string]interface{} `gorm:"-" json:"output-parameter-mapping"`
	Inputparamid         string                 `json:"-"`
	Inputparameter       map[string]interface{} `gorm:"-" json:"input-parameter"`
	Outputparamid        string                 `json:"-"`
	Outputparameter      map[string]interface{} `gorm:"-" json:"output-parameter"`
	Servicebindingid     string                 `json:"-"`
	Servicebinding       Service                `gorm:"-" json:"service-binding"`
	Outputcontextid      string                 `json:"output-context"`
	Overtime             string                 `json:"overtime"`
	Type                 int                    `gorm:"-" json:"type"`
	Transion             []Transion             `gorm:"-" json:"transition"`
	Newtransaction       bool                   `gorm:"newtransaction" json:"newtransaction"`
}

type Script struct {
	Activityid           string                 `json:"id"`
	Name                 string                 `json:"name"`
	Outputparammappingid string                 `json:"-"`
	Outputparammapping   map[string]interface{} `gorm:"-" json:"output-parameter-mapping"`
	Outputparamid        string                 `json:"-"`
	Outputparameter      map[string]interface{} `gorm:"-" json:"output-parameter"`
	Servicebindingid     string                 `json:"-"`
	Servicebinding       Service                `gorm:"-" json:"service-binding"`
	Outputcontextid      string                 `json:"output-context"`
	Overtime             string                 `json:"overtime"`
	Type                 int                    `json:"type"`
	Transion             []Transion             `gorm:"-" json:"transition"`
}

type Service struct {
	Serviceid      string `json:"-"`
	Project        string `json:"project"`
	Serviceabsname string `json:"serviceabsname"`
}

type MsgParamMapping struct {
	Msgbeanmappingid string
	Seq              int8
	Mappingid        string
}

type Mapping struct {
	Mappingid string `json:"-"`
	Type      string `json:"type"`
	From      string `json:"from"`
	Value     string `json:"value"`
	To        string `json:"to"`
}

type Activitys struct {
	Activitiesid         string
	Activityid           string
	Inputparammappingid  string `gorm:"-" json:"-"`
	Outputparammappingid string `gorm:"-" json:"-"`
	Seq                  string
	Type                 int
}

type Catagory struct {
	Catagoryid   string
	Cgtype       string
	Intfname     string
	Intfabsname  string
	Parentid     string
	CatagorySub  []interface{}    `gorm:"-" `
	AtomSvrLst   *[]AtomSvrDefine `gorm:"-" `
	Catagorydesc string
	ProcessSub   map[string]interface{} `gorm:"-" `
	ProcessLst   *[]Process             `gorm:"-" `
}

type Genesrcdefine struct {
	genetype string
	srcpath  string
}

type GenebeanParammsg struct {
	Inparamid    string
	Outparamid   string
	Catagorytype string
	Subpath      string
}

func getProcessbyCataid(cataid string, issubprocess bool) (processLst []Process, count int64) {
	db.Table("process").Where("catagoryid = ? and issubprocess = ?", cataid, issubprocess).Find(&processLst).Count(&count)

	for i, _ := range processLst {
		processLst[i].Inputparameter = map[string]interface{}{"parameter": getParameter(processLst[i].Inputparamid, "")}
		processLst[i].Outputparameter = map[string]interface{}{"parameter": getParameter(processLst[i].Outputparamid, "")}
		//获取原子服务
		processLst[i].Activities = map[string][]interface{}{"activity": getActivities(processLst[i].Activitiesid)}
		//获取分支
		processLst[i].Transion = getTransion(processLst[i].Processid, "0")
	}
	return processLst, count
}

func getParameter(paramid string, relname string) map[string]interface{} {

	var param Parameter

	db.Table("parameter").Where("parameterid = ?", paramid).Find(&param)
	var paramMap = make(map[string]interface{})
	if relname == "" {
		paramMap["name"] = param.Name
	} else {
		paramMap["name"] = relname
	}
	paramMap["classPath"] = param.Classpath
	paramMap["optional"] = param.Optional
	paramMap["type"] = param.Type

	var paramrel []Paramrelation
	var count int64
	db.Table("paramrelation").Where("parentparamid = ?", paramid).Find(&paramrel).Count(&count)

	if count == 0 {
		return paramMap
	}

	if param.Type == "List" {
		//list中元素为基本类型或子parameter，不允许使用javaMap(HashMap)
		var paramrs []map[string]interface{}
		pl := paramrel[0]
		//如果元素为parameter，对子参数进行递归遍历
		if len([]rune(pl.Subparamid)) == 32 {
			paramrsubs := getParameter(pl.Subparamid, pl.Relname)
			paramrs = append(paramrs, paramrsubs)
			paramMap["parameter"] = paramrs
		} else {
			//如果子参数是基本类型，只需要新增一次
			var param = make(map[string]interface{})
			param["type"] = pl.Subparamid
			paramrs = append(paramrs, param)
			paramMap["parameter"] = paramrs
		}
	} else if param.Type == "Map" {
		var paramrs []map[string]interface{}
		for _, pl := range paramrel {
			if pl.Reltype == "sub" {
				paramrsubs := getParameter(pl.Subparamid, pl.Relname)
				paramrs = append(paramrs, paramrsubs)
			}
		}
		paramMap["parameter"] = paramrs
	}

	return paramMap
}

func getActivities(actsid string) []interface{} {
	var acts []Activitys
	var acti []interface{}

	db.Table("activities").Where("activitiesid = ?", actsid).Order("seq").Find(&acts)

	for _, actsitem := range acts {
		switch actsitem.Type {
		case 0:
			activity := getActivity(actsitem.Activityid)
			activity.Type = actsitem.Type
			acti = append(acti, activity)
		case 1:
			loop := GetLoop(actsitem.Activityid)
			loop.Type = actsitem.Type
			acti = append(acti, loop)
		case 2:
			script := getSript(actsitem.Activityid)
			script.Type = actsitem.Type
			acti = append(acti, script)
		case 3:
			subprocess := Getsubprocess(actsitem.Activityid)
			subprocess.Type = actsitem.Type
			acti = append(acti, subprocess)
		default:

		}
	}
	return acti
}

func CreateService(serv Service) {
	db.Table("service").Create(serv)
}

func GetServiceByName(serabsname string) (serv Service, count int64) {
	db.Table("service").Where("serviceabsname = ?", serabsname).Find(&serv).Count(&count)
	return serv, count
}

func getService(servid string) Service {
	var serv Service

	db.Table("service").Where("serviceid = ?", servid).Find(&serv)

	return serv
}

func getMapping(mapid string) Mapping {
	var mapi Mapping

	db.Table("mapping").Where("mappingid = ?", mapid).Find(&mapi)

	return mapi
}

func getMsgMapping(msgMapid string) interface{} {
	var msgMappingSlice []MsgParamMapping
	var mappingSlice []Mapping

	db.Table("massagebeanmapping").Where("msgbeanmappingid = ?", msgMapid).Order("seq").Find(&msgMappingSlice)

	for _, msgMapItem := range msgMappingSlice {
		mappingSlice = append(mappingSlice, getMapping(msgMapItem.Mappingid))
	}

	var mappingmap = make(map[string]interface{})
	mappingmap["mapping"] = mappingSlice
	//再包一层mapping
	return mappingmap
}

func getActivity(actid string) Activity {
	var act Activity

	db.Table("activity").Where("activityid = ?", actid).Find(&act)

	//获取原子服务出入参
	act.Inputparameter = map[string]interface{}{"parameter": getParameter(act.Inputparamid, "")}
	act.Outputparameter = map[string]interface{}{"parameter": getParameter(act.Outputparamid, "")}

	//获取原子服务绑定
	act.Servicebinding = getService(act.Servicebindingid)

	//获取原子服务参数映射
	act.Inputparammapping = map[string]interface{}{"massage-bean-mapping": getMsgMapping(act.Inputparammappingid)}
	act.Outputparammapping = map[string]interface{}{"massage-bean-mapping": getMsgMapping(act.Outputparammappingid)}

	//获取分支
	act.Transion = getTransion(act.Activityid, "0")

	return act
}

func getSript(actid string) Script {
	var script Script
	db.Table("script").Where("activityid = ?", actid).Find(&script)

	//获取脚本出参
	script.Outputparameter = map[string]interface{}{"parameter": getParameter(script.Outputparamid, "")}

	//获取脚本服务绑定
	script.Servicebinding = getService(script.Servicebindingid)

	//获脚本服务参数映射
	script.Outputparammapping = map[string]interface{}{"massage-bean-mapping": getMsgMapping(script.Outputparammappingid)}

	//获取分支
	script.Transion = getTransion(script.Activityid, "0")

	return script
}

func GetProcess(name string) *FullProcess {
	var fullProcess FullProcess
	process := GetCommonProcess(name)
	fullProcess.Process = *process
	return &fullProcess
}

func GetCommonProcess(name string) *Process {

	var process Process

	//获取编排服务主数据
	db.Table("process").Where("name	= ?", name).Find(&process)

	//获取编排服务出入参数据
	process.Inputparameter = map[string]interface{}{"parameter": getParameter(process.Inputparamid, "")}
	process.Outputparameter = map[string]interface{}{"parameter": getParameter(process.Outputparamid, "")}

	//获取原子服务
	process.Activities = map[string][]interface{}{"activity": getActivities(process.Activitiesid)}

	//获取分支
	process.Transion = getTransion(process.Processid, "1")

	return &process
}

var genebeanmsgList []GenebeanParammsg
var updParams []map[string]interface{}

func BatchUpdate(params []map[string]interface{}) error {
	tx := db.Begin()
	for _, param := range params {
		updDict2(param, tx)
	}
	tx.Commit()
	return nil
}

func AddProcess(fullProcess FullProcess) interface{} {
	process := fullProcess.Process
	process.Issubprocesss = false
	process.Catagoryid = "7de2c8823c4d45e299ba3d2fa00eefa5"
	return AddCommonProcess(process)
}

// 通用编排服务新增方法
func AddCommonProcess(process Process) interface{} {
	var resp Response
	var inputparamid string
	var outputparamid string
	var inDataParamid string
	var outDataParamid string
	var projectid string
	msgbms := []MsgParamMapping{}
	mapps := []Mapping{}
	paramMap := map[string]Parameter{}
	paramRelas := []Paramrelation{}
	genebeanmsg := make(map[string]interface{})
	activitiesList := []Activitys{}
	transionList := []Transion{}
	services := []Service{}
	activityList := []Activity{}
	activities := process.Activities["activity"]
	genebeanmsgList = []GenebeanParammsg{}
	updParams = []map[string]interface{}{}
	projectid = process.Projectid
	//编排服务唯一性校验
	var count int64
	db.Table("process").Where("name	= ?", process.Name).Count(&count)
	if count > 0 {
		genebeanmsg["respCode"] = "000001"
		genebeanmsg["respMsg"] = "process already exist"
		return genebeanmsg
	}

	activitiesid := addActivities(activities, &activitiesList, &msgbms, &mapps, paramMap, &paramRelas, &transionList,
		&services, &activityList, process.Name)
	if process.Inputparameter["parameter"] != nil {
		datanode := getParamDataNode(process.Inputparameter["parameter"].(map[string]interface{}))
		if datanode != nil {
			inputparamid = addParameter(datanode, paramMap, &paramRelas)
			inDataParamid = inputparamid
		}
	} else {
		inputparamid = uuidutil.GetUUID()
	}
	if process.Outputparameter["parameter"] != nil {
		datanode := getParamDataNode(process.Outputparameter["parameter"].(map[string]interface{}))
		if datanode != nil {
			outputparamid = addParameter(datanode, paramMap, &paramRelas)
			outDataParamid = outputparamid
		}
	} else {
		outputparamid = uuidutil.GetUUID()
	}

	processid := uuidutil.GetUUID()

	if process.Transion != nil {
		addTransion(processid, process.Transion, "1", &transionList)
	}
	err := db.Table("process").CreateInBatches([]map[string]interface{}{{
		"name":          process.Name,
		"overtime":      process.Overtime,
		"version":       process.Version,
		"inputparamid":  inputparamid,
		"activitiesid":  activitiesid,
		"processid":     processid,
		"outputparamid": outputparamid,
		"projectname":   projectid,
		"catagoryid":    process.Catagoryid,
		"desc":          process.Desc,
		"issubprocess":  process.Issubprocesss,
	}}, 1)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err":       err,
			"processid": process.Processid,
		}).Error("create process err.")
		resp.RespCode = "000001"
		resp.RespMsg = err.Error.Error()
		return resp
	}
	error := saveAll(msgbms, mapps, paramMap, paramRelas, activitiesList, transionList, services, activityList)

	if len(updParams) > 0 {
		err := BatchUpdate(updParams)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("scan err, update dict error.")
		}
	}
	if nil != error {
		global.LOG.WithFields(logrus.Fields{
			"err": error,
		}).Error("addProcess err, error.")
		return err
	}

	genebeanmsg["processname"] = process.Name

	genebeanmsgList = append(genebeanmsgList, GenebeanParammsg{
		Inparamid:  inDataParamid,
		Outparamid: outDataParamid,
		Subpath:    "",
	})

	genebeanmsg["genebeanmsgList"] = genebeanmsgList

	genebeanmsg["processid"] = processid
	return genebeanmsg
}

func saveAll(msgbms []MsgParamMapping, mapps []Mapping, paramMap map[string]Parameter,
	paramRelas []Paramrelation, activitiesList []Activitys, transionList []Transion, services []Service,
	activityList []Activity) error {
	if len(msgbms) > 0 {
		err := saveMsgBeanMappings(msgbms)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("addProcess err, saveMsgBeanMappings error.")
			return err
		}
	}
	if len(mapps) > 0 {
		err := saveMappings(mapps)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("addProcess err, saveMappings error.")
			return err
		}
	}
	if len(paramMap) > 0 {
		params := getParams(paramMap)
		err := SaveParams(params)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("addProcess err, SaveParams error.")
			return err
		}
	}
	if len(activitiesList) > 0 {
		err := SaveActivitys(activitiesList)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("addProcess err, SaveActivities error.")
			return err
		}
	}
	if len(transionList) > 0 {
		err := SaveTransions(transionList)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("addProcess err, SaveTransions error.")
			return err
		}
	}
	if len(services) > 0 {
		err := SaveAsvs(services)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("addProcess err, saveService error.")
			return err
		}
	}
	if len(activityList) > 0 {
		err := SaveActivityList(activityList)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("addProcess err, SaveActivityList error.")
			return err
		}
	}
	if len(paramRelas) > 0 {
		err := SaveParamRelas(paramRelas)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("addProcess err, SaveParamRelas error.")
			return err
		}
	}
	return nil
}

func getParams(pMap map[string]Parameter) []Parameter {
	params := []Parameter{}
	if len(pMap) > 0 {
		for _, param := range pMap {
			params = append(params, param)
		}
	}
	return params
}

func addActivities(activities []interface{}, activitiesList *[]Activitys, msgbms *[]MsgParamMapping,
	mapps *[]Mapping, paramMap map[string]Parameter, paramRelas *[]Paramrelation,
	transionList *[]Transion, services *[]Service, activityList *[]Activity, processname string) string {
	activitiesid := uuidutil.GetUUID()
	seq := 1
	for _, act := range activities {

		activity := act.(map[string]interface{})
		global.LOG.Infof("当前添加原子服务名称为%d", activity[""])
		fmt.Println("act name ", activity["name"])
		activitytype := activity["type"].(float64)
		activityid := activity["id"]
		resByre, resByteErr := json.Marshal(act)
		if resByteErr != nil {
			fmt.Printf("%v", resByteErr)
			return resByteErr.Error()
		}
		switch activitytype {
		case float64(0):
			var definedactivity Activity
			jsonRes := json.Unmarshal(resByre, &definedactivity)
			if jsonRes != nil {
				fmt.Printf("%v", jsonRes)
				return jsonRes.Error()
			}
			addActivity(definedactivity, msgbms, mapps, paramMap, paramRelas, transionList, activityList)
		case float64(1):
			var loop Loop
			jsonRes := json.Unmarshal(resByre, &loop)
			if jsonRes != nil {
				fmt.Printf("%v", jsonRes)
				return jsonRes.Error()
			}
			AddLoop(loop, activitiesList, msgbms, mapps, paramMap, paramRelas, transionList, services, activityList, processname)
		case float64(2):
			var script Script
			jsonRes := json.Unmarshal(resByre, &script)
			if jsonRes != nil {
				fmt.Printf("%v", jsonRes)
				return jsonRes.Error()
			}
			addScript(script, msgbms, mapps, paramMap, paramRelas, transionList, services)
		case float64(3):
			var subprocess Subprocess
			jsonRes := json.Unmarshal(resByre, &subprocess)
			if jsonRes != nil {
				fmt.Printf("%v", jsonRes)
				return jsonRes.Error()
			}
			Addsubprocess(subprocess, msgbms, mapps, transionList)
		default:
			return "activity type error!"
		}

		*activitiesList = append(*activitiesList, Activitys{
			Activitiesid: activitiesid,
			Activityid:   activityid.(string),
			Seq:          string(seq),
			Type:         int(activitytype),
		})
		seq = seq + 1
	}
	return activitiesid
}

func addScript(script Script, msgbms *[]MsgParamMapping, mapps *[]Mapping, paramMap map[string]Parameter,
	paramRelas *[]Paramrelation, transionList *[]Transion, services *[]Service) {
	outputparameter := script.Outputparameter
	service := script.Servicebinding
	name := script.Name
	overtime := script.Overtime
	outputparamid := addParameter(outputparameter["parameter"].(map[string]interface{}), paramMap, paramRelas)

	outputparammap := script.Outputparammapping["massage-bean-mapping"].(map[string]interface{})
	outputparammapping := getMappings(outputparammap["mapping"].([]interface{}))
	outputparammappingid := addMsgMapping(outputparammapping, msgbms, mapps)
	servicebindingid := addService(service, services)
	if script.Transion != nil {
		addTransion(script.Activityid, script.Transion, "0", transionList)
	}

	err := db.Exec("INSERT INTO script(name, activityid, outputparamid,  outputparammappingid, servicebindingid, overtime) VALUES($1, $2, $3, $4, $5, $6)",
		name, script.Activityid, outputparamid, outputparammappingid, servicebindingid, overtime)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err":      err,
			"scriptid": script.Activityid,
		}).Error("add activityid err.")
	}
}

func getAtomSvr(atomsvrid string) AtomSvrDefine {
	var atomsvrdefine AtomSvrDefine
	db.Table("atomsvrdefine").Where("atomsvrid = ?", atomsvrid).Find(&atomsvrdefine)
	return atomsvrdefine
}

func addActivity(activity Activity, msgbms *[]MsgParamMapping, mapps *[]Mapping, paramMap map[string]Parameter,
	paramRelas *[]Paramrelation, transionList *[]Transion, activityList *[]Activity) {
	inputparameter := activity.Inputparameter
	outputparameter := activity.Outputparameter
	name := activity.Name
	overtime := activity.Overtime
	var inputparamid string
	var outputparamid string

	//从atomsvrdefine表中查询原子服务是否已存在
	var existatom int64
	var atomsvrdefine AtomSvrDefine
	db.Table("atomsvrdefine").Where("asname = ?", name).Find(&atomsvrdefine).Count(&existatom)
	if existatom > 0 {
		inputparamid = atomsvrdefine.Inputparamid
		outputparamid = atomsvrdefine.Outputparamid
	} else {
		indatanode := getParamDataNode(inputparameter["parameter"].(map[string]interface{}))
		if indatanode != nil {
			inputparamid = addParameter(indatanode, paramMap, paramRelas)
		}
		outdatanode := getParamDataNode(outputparameter["parameter"].(map[string]interface{}))
		if outdatanode != nil {
			outputparamid = addParameter(outdatanode, paramMap, paramRelas)
		}
	}

	inputparammappingid := ""
	if activity.Inputparammapping["massage-bean-mapping"] != nil {
		inputparammap := activity.Inputparammapping["massage-bean-mapping"].(map[string]interface{})
		if inputparammap["mapping"] != nil {
			inputparammapping := getMappings(inputparammap["mapping"].([]interface{}))
			inputparammappingid = addMsgMapping(inputparammapping, msgbms, mapps)
		}

	}
	outputparammappingid := ""
	if activity.Outputparammapping["massage-bean-mapping"] != nil {
		outputparammap := activity.Outputparammapping["massage-bean-mapping"].(map[string]interface{})
		if outputparammap["mapping"] != nil {
			outputparammapping := getMappings(outputparammap["mapping"].([]interface{}))
			outputparammappingid = addMsgMapping(outputparammapping, msgbms, mapps)
		}

	}

	servicebindingid := atomsvrdefine.Servicebindingid

	if activity.Transion != nil {
		addTransion(activity.Activityid, activity.Transion, "0", transionList)
	}

	*activityList = append(*activityList, Activity{
		Activityid:           activity.Activityid,
		Name:                 name,
		Inputparammappingid:  inputparammappingid,
		Outputparammappingid: outputparammappingid,
		Inputparamid:         inputparamid,
		Outputparamid:        outputparamid,
		Servicebindingid:     servicebindingid,
		Overtime:             overtime,
		Newtransaction:       activity.Newtransaction,
	})
}

func AddParamrelation(pl *Paramrelation) {
	db.Table("paramrelation").Create(pl)
}

func AddParameter(parameter map[string]interface{}) string {
	paramMap := map[string]Parameter{}
	res := reflushParameterItem(parameter, paramMap)
	saveAll(nil, nil, paramMap, nil, nil, nil, nil, nil)
	return res
}

func reflushParameterItem(parameter map[string]interface{}, paramMap map[string]Parameter) string {

	name := parameter["name"]
	classpath := parameter["classPath"]
	var optional string
	if _, ok := parameter["optional"]; !ok {
		optional = ""
	} else {
		optional = parameter["optional"].(string)
	}
	parametertype := parameter["type"]
	if parametertype == "Map" && classpath != nil {
		strarr := strings.Split(classpath.(string), ".")
		name = strarr[len(strarr)-1]
	} else if parametertype == "Map" && classpath == nil {
		//当前map为编排服务的出参和入参时,暂时存空，之后再根据编排服务名称生成参数名和classpath
		name = ""
		classpath = ""
	}

	global.LOG.Info(name.(string) + classpath.(string))
	//更新数据字典中对应的参数信息
	updDict(map[string]interface{}{
		"name":      name,
		"type":      parametertype,
		"classpath": classpath,
	})
	//在parameter表中存入参数信息
	paramid := uuidutil.GetUUID()
	paramMap[paramid] = Parameter{
		Parameterid: paramid,
		Name:        name.(string),
		Type:        parametertype.(string),
		Optional:    string(optional),
		Classpath:   classpath.(string),
	}
	return paramid
}

func updDict(param map[string]interface{}) string {
	var pold map[string]interface{}
	var count int64
	db.Table("paramdefine").Where("name = ?", param["name"]).Find(&pold).Count(&count)
	delete(param, "optional")
	if count == 0 {
		param["parameterid"] = uuidutil.GetUUID()

		db.Table("paramdefine").CreateInBatches(param, 1)
		return param["parameterid"].(string)
	} else {
		db.Table("paramdefine").Where("parameterid = ?", pold["parameterid"]).Updates(param)
		return pold["parameterid"].(string)
	}
}

func updDict2(param map[string]interface{}, db *gorm.DB) string {
	var pold map[string]interface{}
	var count int64
	db.Table("paramdefine").Where("name = ?", param["name"]).Find(&pold).Count(&count)
	delete(param, "optional")
	if count == 0 {
		param["parameterid"] = uuidutil.GetUUID()

		db.Table("paramdefine").CreateInBatches(param, 1)
		return param["parameterid"].(string)
	} else {
		db.Table("paramdefine").Where("parameterid = ?", pold["parameterid"]).Updates(param)
		return pold["parameterid"].(string)
	}
}

func addParameter(parameter map[string]interface{}, paramMap map[string]Parameter, paramRelas *[]Paramrelation) string {
	paramid := reflushParameterItem(parameter, paramMap)

	//更新param时，需要先清理存量rel
	DeleteParamRel(paramid)

	parametertype := parameter["type"]

	if parametertype == "List" {
		var subparam map[string]interface{}
		if _, ok := parameter["parameter"].(map[string]interface{}); ok {
			subparam = parameter["parameter"].(map[string]interface{})
		} else {
			subparam = parameter["parameter"].([]interface{})[0].(map[string]interface{})
		}
		//根据List中的元素类型新增；List中的元素为dto（isbasetype=1）、基本数据类型
		if _, ok := subparam["type"]; ok {
			elementype := subparam["type"]
			if elementype == "Map" {
				subparamid := addParameter(subparam, paramMap, paramRelas)
				addOrUpdateParamRel(paramid, subparamid, "lst", "1", "", paramRelas)
			} else {
				subparamid := subparam["type"]
				addOrUpdateParamRel(paramid, subparamid.(string), "lst", "0", "", paramRelas)
			}
		}
	} else if parametertype == "Map" {
		//递归新增
		if _, ok := parameter["parameter"]; ok {
			fmt.Println(parameter["parameter"])
			subparams := parameter["parameter"].([]interface{})
			for _, subParam := range subparams {
				subparamid := addParameter(subParam.(map[string]interface{}), paramMap, paramRelas)
				//新增parameter层级关系
				if (subParam.(map[string]interface{})["type"]) == "Map" {
					addOrUpdateParamRel(paramid, subparamid, "sub", "1", subParam.(map[string]interface{})["name"].(string), paramRelas)
				} else {
					addOrUpdateParamRel(paramid, subparamid, "sub", "0", "", paramRelas)
				}
			}
		}
	}
	return paramid
}

// 删除参数及其全部子参数信息
func delParameter(paramid string) {
	db.Exec("DELETE FROM parameter where parameterid = $1", paramid)
	var paramrel []Paramrelation
	db.Table("paramrelation").Where("parentparamid = ?", paramid).Find(&paramrel)
	for _, subparam := range paramrel {
		subparamid := subparam.Subparamid
		db.Exec("DELETE FROM paramrelation where parameterid = $1 and subparamid = $2", paramid, subparamid)
		if len([]rune(subparamid)) == 32 {
			delParameter(subparamid)
		}
	}
}

// 删除某个参数的全部关联信息
func DeleteParamRel(paramid string) {
	db.Exec("delete from paramrelation  where parentparamid=$1", paramid)
}

// 新增或更新参数关联信息
func addOrUpdateParamRel(parentparamid string, subparamid string, reltype string, isbasetype string, relname string, paramRelas *[]Paramrelation) {
	var count int64
	db.Table("paramrelation").Where("parentparamid = ? and subparamid =?", parentparamid, subparamid).Count(&count)
	if count == 0 {
		*paramRelas = append(*paramRelas, Paramrelation{
			Parentparamid: parentparamid,
			Subparamid:    subparamid,
			Reltype:       reltype,
			Isbasetype:    isbasetype,
			Relname:       relname,
		})
	}
}

func addService(service Service, services *[]Service) string {
	serviceid := uuidutil.GetUUID()
	service.Serviceid = serviceid
	*services = append(*services, service)
	return serviceid
}

func addMsgMapping(mappings []Mapping, msgbms *[]MsgParamMapping, mapps *[]Mapping) string {
	msgmappingid := uuidutil.GetUUID()
	var seq int8 = 1

	for _, mapppingItem := range mappings {
		mappingid := uuidutil.GetUUID()
		mapppingItem.Mappingid = mappingid
		*mapps = append(*mapps, mapppingItem)
		*msgbms = append(*msgbms, MsgParamMapping{
			Msgbeanmappingid: msgmappingid,
			Seq:              seq,
			Mappingid:        mappingid,
		})
		seq = seq + 1
	}

	return msgmappingid
}

func addMapping(mapping Mapping) string {
	mappingid := uuidutil.GetUUID()
	fmt.Printf("mappingid: %s, %s, %s, %s, %s\n", mappingid, mapping.From, mapping.To, mapping.Type, mapping.Value)
	err := db.Exec("INSERT INTO mapping(mappingid, `from`, `to`, type, value) VALUES($1, $2, $3, $4, $5)",
		mappingid, mapping.From, mapping.To, mapping.Type, mapping.Value)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err":       err,
			"mappingid": mappingid,
		}).Error("add mapping err.")
		return ""
	} else {
		return mappingid
	}
}

func getParamDataNode(rootparam map[string]interface{}) map[string]interface{} {
	if rootparam["parameter"] == nil {
		return nil
	}
	paramLst := rootparam["parameter"].([]interface{})
	for _, node := range paramLst {
		if "data" == node.(map[string]interface{})["name"].(string) {
			return node.(map[string]interface{})
		}
	}
	return nil
}

func UpdateProcess(fullProcess FullProcess) interface{} {
	process := fullProcess.Process
	process.Issubprocesss = false
	return UpdateCommonProcess(process)
}

// 编排服务更新相关方法
func UpdateCommonProcess(process Process) interface{} {
	activities := process.Activities["activity"]

	msgbms := []MsgParamMapping{}
	mapps := []Mapping{}
	paramMap := map[string]Parameter{}
	paramRelas := []Paramrelation{}
	activitiesList := []Activitys{}
	transionList := []Transion{}
	services := []Service{}
	activityList := []Activity{}
	genebeanmsgList = []GenebeanParammsg{}

	var inDataParamid string
	var outDataParamid string

	if activities != nil {
		process.Activitiesid = addActivities(activities, &activitiesList, &msgbms, &mapps, paramMap, &paramRelas, &transionList,
			&services, &activityList, process.Name)
	}

	//查询编排服务之前的出入参
	var originprocess Process
	db.Table("process").Where("processid=?  ", process.Processid).Find(&originprocess)
	//删除数据库里之前的参数信息,再进行新增
	delParameter(originprocess.Inputparamid)
	delParameter(originprocess.Outputparamid)

	if process.Inputparameter["parameter"] != nil {
		datanode := getParamDataNode(process.Inputparameter["parameter"].(map[string]interface{}))
		if datanode != nil {
			process.Inputparamid = addParameter(datanode, paramMap, &paramRelas)
			inDataParamid = process.Inputparamid
		}
	}
	if process.Outputparameter["parameter"] != nil {
		datanode := getParamDataNode(process.Outputparameter["parameter"].(map[string]interface{}))
		if datanode != nil {
			process.Outputparamid = addParameter(datanode, paramMap, &paramRelas)
			outDataParamid = process.Outputparamid
		}
	}

	//先将之前的transion逻辑删除，再新增新的transion
	updateTransion(process.Processid, "0")
	if process.Transion != nil {
		addTransion(process.Processid, process.Transion, "1", &transionList)
	}

	//更新编排服务文件夹名称及文件名称
	renameProcessFile(process.Processid, process.Name)

	//更新有变化的属性
	err := db.Table("process").Where("processid=?  ", process.Processid).Updates(process)
	genebeanmsg := make(map[string]interface{})
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err":       err,
			"processid": process.Processid,
		}).Error("update process err.")
		genebeanmsg["respCode"] = "000001"
		genebeanmsg["respMsg"] = err.Error.Error()
		return genebeanmsg
	}

	error := saveAll(msgbms, mapps, paramMap, paramRelas, activitiesList, transionList, services, activityList)
	if nil != error {
		global.LOG.WithFields(logrus.Fields{
			"err": error,
		}).Error("addProcess err, error.")
		return err
	}

	genebeanmsg["processname"] = process.Name

	genebeanmsgList = append(genebeanmsgList, GenebeanParammsg{
		Inparamid:  inDataParamid,
		Outparamid: outDataParamid,
		Subpath:    "",
	})

	genebeanmsg["genebeanmsgList"] = genebeanmsgList
	return genebeanmsg
}

func GetSrcPath() string {
	srcpath := GetGeneSrcDefine("composebean").Srcpath
	srcpath = "com." + strings.Split(srcpath, "com\\")[1]
	srcpath = strings.Replace(srcpath, "\\", ".", -1)
	return srcpath
}

// 编排服务列表查询
func GetProcessLst(name string, projectName string, page int, pagesize int, issubprocess bool) interface{} {
	var total int64
	db.Table("process").Where("name like ? and projectname like ? and issubprocess = ?", name+"%", projectName+"%", issubprocess).Count(&total)
	var processLst []Process
	db.Table("process").Where("name like ? and projectname like ? and issubprocess = ?", name+"%", projectName+"%", issubprocess).Limit(pagesize).Offset((page - 1) * pagesize).Find(&processLst)
	var dataMap = make(map[string]interface{})
	dataMap["total"] = total
	dataMap["data"] = processLst
	return dataMap
}

func GetProcessJson(processname string) interface{} {
	// 从数据库中读取json地址
	localpath := GetLocalPath("00001").LocalPath
	fmt.Println(localpath)
	srcpath := GetGeneSrcDefine("composejson").Srcpath
	jsonpath := localpath + global.PTHSEP + srcpath + global.PTHSEP + processname + global.PTHSEP + "origin.json"
	fmt.Println(jsonpath)

	jsonfile, err := os.Open(jsonpath)
	if err != nil {
		fmt.Println("读取json文件失败", err)
		return err.Error()
	}
	decoder := json.NewDecoder(jsonfile)

	var frontjson interface{}
	decoder.Decode(&frontjson)
	return frontjson
}

func renameFolder(oldpath string, newpath string) {
	folderRenameErr := os.Rename(oldpath, newpath)
	if folderRenameErr != nil {
		global.LOG.WithFields(logrus.Fields{
			"folderRenameErr": folderRenameErr,
			"oldpath":         oldpath,
			"newpath":         newpath,
		}).Error("rename folder name err.")
	}
}

func renameFile(oldname string, newname string) {
	fileRenameErr := os.Rename(oldname, newname)
	if fileRenameErr != nil {
		global.LOG.WithFields(logrus.Fields{
			"fileRenameErr": fileRenameErr,
			"oldname":       oldname,
			"newname":       newname,
		}).Error("rename file name err.")
	}
}

func renameProcessFile(processid string, newname string) {
	var originprocess Process
	//查询被更新编排服务原名
	db.Table("process").Where("processid=?  ", processid).Find(&originprocess)
	originname := originprocess.Name

	localpath := GetLocalPath("00001").LocalPath
	fmt.Println(localpath)

	// 重命名json文件夹
	srcpath := GetGeneSrcDefine("composejson").Srcpath
	jsonfolderpath := localpath + global.PTHSEP + srcpath + global.PTHSEP + originname
	newjsonfoldername := localpath + global.PTHSEP + srcpath + global.PTHSEP + newname
	renameFolder(jsonfolderpath, newjsonfoldername)

	// 重命名json文件
	filepath := newjsonfoldername + global.PTHSEP + originname + ".json"
	newfilename := newjsonfoldername + global.PTHSEP + newname + ".json"
	renameFile(filepath, newfilename)

	//重命名出入参文件夹
	srcpath = GetGeneSrcDefine("composebean").Srcpath
	paramfolderpath := localpath + global.PTHSEP + srcpath + global.PTHSEP + originname
	newparamfolderpath := localpath + global.PTHSEP + srcpath + global.PTHSEP + newname
	renameFolder(paramfolderpath, newparamfolderpath)

	//重命名出入参类名
	inparamfilepath := newparamfolderpath + global.PTHSEP + stringutil.GetTitleStr(originname) + "In.java"
	inparamnewfilename := newparamfolderpath + global.PTHSEP + stringutil.GetTitleStr(newname) + "In.java"
	renameFile(inparamfilepath, inparamnewfilename)

	outparamfilepath := newparamfolderpath + global.PTHSEP + stringutil.GetTitleStr(originname) + "Out.java"
	outparamnewfilename := newparamfolderpath + global.PTHSEP + stringutil.GetTitleStr(newname) + "Out.java"
	renameFile(outparamfilepath, outparamnewfilename)

}
